using System;
using System.Collections.Generic;
using Xunit;
using WenYu.Core.Lexer;
using WenYu.Core.Parser;

namespace WenYu.Tests.DocumentValidation;

/// <summary>
/// 文档03-运算符.md的示例验证测试
/// </summary>
public class Doc03OperatorsValidation
{
    private List<Token> Tokenize(string source)
    {
        var lexer = new WenYuLexer(source);
        return lexer.Tokenize();
    }

    private Program Parse(string source)
    {
        var lexer = new WenYuLexer(source);
        var tokens = lexer.Tokenize();
        var parser = new WenYuParser(tokens);
        return parser.Parse();
    }

    #region 算术运算符测试

    [Fact]
    public void Example1_ArithmeticOperators_Basic()
    {
        var source = @"整型 甲 是 10。
整型 乙 是 3。
整型 和 是 甲 + 乙。
整型 差 是 甲 - 乙。
整型 积 是 甲 * 乙。
整型 商 是 甲 ÷ 乙。
整型 余数 是 甲 % 乙。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        // Check arithmetic operators
        Assert.Contains("+", tokenValues);
        Assert.Contains("-", tokenValues);
        Assert.Contains("*", tokenValues);
        Assert.Contains("÷", tokenValues);
        Assert.Contains("%", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example2_ArithmeticOperators_Float()
    {
        var source = @"实型 甲 是 10.0。
实型 乙 是 3.0。
实型 商 是 甲 ÷ 乙。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example3_StringConcatenation()
    {
        var source = @"文字 姓 是 ""张""。
文字 名 是 ""三""。
文字 全名 是 姓 + 名。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example4_MixedArithmetic()
    {
        var source = @"整型 结果 是 10 + 5 * 2 - 3。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 比较运算符测试

    [Fact]
    public void Example5_ComparisonOperators()
    {
        var source = @"整型 甲 是 10。
整型 乙 是 5。
真假 结果1 是 甲 》 乙。
真假 结果2 是 甲 《 乙。
真假 结果3 是 甲 不《 乙。
真假 结果4 是 甲 不》 乙。
真假 结果5 是 甲 同 乙。
真假 结果6 是 甲 不同 乙。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        // Check comparison operators
        Assert.Contains("》", tokenValues);
        Assert.Contains("《", tokenValues);
        Assert.Contains("不《", tokenValues);
        Assert.Contains("不》", tokenValues);
        Assert.Contains("同", tokenValues);
        Assert.Contains("不同", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example6_ComparisonInCondition()
    {
        var source = @"整型 分数 是 85。
若 分数 不《 90 则{
    输出（""优秀！""）。
}余{
    输出（""不及格。""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 逻辑运算符测试

    [Fact]
    public void Example7_LogicalAND()
    {
        var source = @"真假 作业完成了 是 真真。
真假 下雨了 是 假假。
真假 可以出去玩 是 作业完成了 且 不 下雨了。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("且", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example8_LogicalOR()
    {
        var source = @"真假 周末 是 真真。
真假 放假 是 假假。
真假 可以休息 是 周末 或 放假。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("或", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example9_LogicalNOT()
    {
        var source = @"真假 下雨了 是 假假。
真假 晴天 是 不 下雨了。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("不", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example10_ComplexLogical()
    {
        var source = @"整型 年龄 是 10。
整型 分数 是 85。
真假 是学生 是 真真。
若 (年龄 》 8 且 年龄 《 18) 且 分数 不《 60 且 是学生 则{
    输出（""合格学生""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 自增自减测试

    [Fact]
    public void Example11_IncrementDecrement()
    {
        var source = @"整型 计数 是 0。
计数++。
计数++。
计数++。
计数--。
计数--。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        // Check for ++ and --
        Assert.Contains("++", tokenValues);
        Assert.Contains("--", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 完整示例测试

    [Fact]
    public void Example12_Calculator()
    {
        var source = @"输出（""===四则运算计算器===""）。
整型 数一 是 20。
整型 数二 是 6。
整型 加法 是 数一 + 数二。
整型 减法 是 数一 - 数二。
整型 乘法 是 数一 * 数二。
整型 除法 是 数一 ÷ 数二。
整型 取余 是 数一 % 数二。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example13_ComplexCondition()
    {
        var source = @"整型 作业完成度 是 100。
真假 下雨了 是 假假。
真假 妈妈同意 是 真真。
真假 作业完成 是 作业完成度 同 100。
真假 天气好 是 不 下雨了。
真假 可以出去玩 是 作业完成 且 天气好 且 妈妈同意。
若 可以出去玩 则{
    输出（""可以出去玩""）。
}余{
    输出（""不能出去玩""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example14_GradeEvaluation()
    {
        var source = @"整型 数学 是 85。
整型 语文 是 92。
整型 英语 是 78。
整型 总分 是 数学 + 语文 + 英语。
整型 平均分 是 总分 ÷ 3。
若 平均分 不《 90 则{
    输出（""优秀""）。
}余{
    输出（""其他""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 特殊情况测试

    [Fact]
    public void Example15_SlashDivision()
    {
        // Test / as alternative to ÷
        var source = @"整型 甲 是 10。
整型 乙 是 3。
整型 商 是 甲 / 乙。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        // Either ÷ or / should be recognized
        bool hasDivision = tokenValues.Contains("÷") || tokenValues.Contains("/");
        Assert.True(hasDivision, "Division operator should be recognized");

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion
}
